ASM code blocks in Emacs Org Mode
Compilling Assembly on Org Mode Source Blocks.
Table of Contents
Introduction
I have recently started reading the book Programming from the Ground Up, which I saw recommended on various threads about learning low level programming and the fundamentals of computing.
The book starts off with some assembly programming. My initial approach to follow the various presented examples and exercises was to write each of them on a separate asm file. This, however, was not a satisfactory workflow for me, because I did not have a good way of structuring my notes.
More specifically, I want to have my source code and notes all on the same file, and I also want to run the source code and get the result on my document.
This is the perfect task for Org Mode, and I ended up hacking something that I feel improved my note taking process, which I am sharing in this post. Hope you enjoy.
Source code in Org files
In Org Mode it's possible to embed and run source code blocks in the org files. This is done via Org Babel, which out of the box supports quite a few languages.
For example, we could write some Python code and run it by pressing C-c
on the code block. This will also display the result, as shown in the following example.
#+begin_src python :results output a = 3 b = 4 print(a + b) #+end_src #+RESULTS: : 7
The #+RESULTS:
line, and the : 7
that follows it, get created automatically by Org Mode when the code of the preceding source block is run.
There are quite a few customization options for this, feel free to read all about it here.
Org Mode with assembly code blocks
Unfortunately, asm does not seem to be part of the list of the official supported languages.
For that reason, I ended up writing my own custom org babel executor, that is, the code that runs when I press C-c
on a code block.
(defun get-temp-file-path (file_name) "Returns the path to a tmp file" (concat temporary-file-directory file_name) ) (defun org-babel-execute:asm (body params) "Compiles, links and runs a single asm file" (let ( (tmp-src-path (get-temp-file-path "code.s")) (tmp-obj-path (get-temp-file-path "obj.o")) (tmp-exe-path (get-temp-file-path "exe")) ) (with-temp-file tmp-src-path (insert body) ) (shell-command (format "as %s -o %s" tmp-src-path tmp-obj-path)) (shell-command (format "ld %s -o %s" tmp-obj-path tmp-exe-path)) (shell-command tmp-exe-path) ) )
The executor is a function with the name org-babel-execute:lang
, where lang is the name of the language of the source block, in my case it's asm.
The function should take the arguments body
and params
, where the first is the code of the source block and the latter it's parameters.
With this executor I can now run the following code on my org files and get the result.
#+begin_src asm .section .data data_items: .long 33,22,77,44,1,200,0 .section .text .globl _start _start: movl $0, %edi movl data_items(,%edi,4), %eax movl %eax, %ebx start_loop: cmpl $0, %eax je loop_exit incl %edi movl data_items(,%edi,4), %eax cmpl %ebx, %eax jle start_loop movl %eax, %ebx jmp start_loop loop_exit: movl $1, %eax int $0x80 #+end_src #+RESULTS: : 200
The result 200 is the exit code of the source block, after it get's compiled and run.
This executor will only compile and link a single code block.
The functionality to compile and link various asm source code blocks and run the resulting program could probably be achieved via the params
executor parameter, but I have not yet experimented with this.
Conclusion
In this post I wrote a simple (hacky) custom asm babel executor which ended up making my note taking much easier, faster and organized. I also got a better understanding on how code blocks get evaluated in Org Mode, and how can I customize this process. This is very valuable knowledge for me, because I will be making use of Org Mode for taking notes of the various programming books I will be reading in the future.
Thanks for reading!